home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C101.ZIP / UUPC11XS.ZIP / UUCICO / MODEM.C < prev    next >
C/C++ Source or Header  |  1992-12-18  |  32KB  |  860 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    m o d e m . c                                                   */
  3. /*                                                                    */
  4. /*    High level modem control routines for UUPC/extended             */
  5. /*                                                                    */
  6. /*    Copyright (c) 1991 by Andrew H. Derbyshire                      */
  7. /*                                                                    */
  8. /*    Change history:                                                 */
  9. /*       21 Apr 91      Create from dcpsys.c                          */
  10. /*--------------------------------------------------------------------*/
  11.  
  12.  
  13. /*--------------------------------------------------------------------*/
  14. /*                          RCS Information                           */
  15. /*--------------------------------------------------------------------*/
  16.  
  17. /*
  18.  *    $Id: MODEM.C 1.7 1992/12/18 12:05:57 ahd Exp $
  19.  *
  20.  *    Revision history:
  21.  *    $Log: MODEM.C $
  22.  * Revision 1.7  1992/12/18  12:05:57  ahd
  23.  * Flag variable packet as obsolete
  24.  *
  25.  * Revision 1.6  1992/11/28  19:51:16  ahd
  26.  * Add program exit time to waiting for callin message
  27.  * Make time parameter to callin() const
  28.  *
  29.  * Revision 1.5  1992/11/22  21:20:45  ahd
  30.  * Use strpool for const string allocation
  31.  *
  32.  * Revision 1.4  1992/11/19  03:01:21  ahd
  33.  * drop rcsid
  34.  *
  35.  * Revision 1.3  1992/11/18  03:48:24  ahd
  36.  * Move check of call window to avoid premature lock file overhead
  37.  *
  38.  * Revision 1.2  1992/11/15  20:12:17  ahd
  39.  * Clean up modem file support for different protocols
  40.  *
  41.  * Revision 1.1  1992/11/12  12:32:18  ahd
  42.  * Initial revision
  43.  *
  44.  * Revision 1.1  1992/05/02  13:06:48  ahd
  45.  * Initial revision
  46.  *
  47.  */
  48.  
  49. /*--------------------------------------------------------------------*/
  50. /*                        System include files                        */
  51. /*--------------------------------------------------------------------*/
  52.  
  53. #include <limits.h>
  54. #include <stdio.h>
  55. #include <stdlib.h>
  56. #include <string.h>
  57. #include <ctype.h>
  58. #include <time.h>
  59. #include <limits.h>
  60. #include <sys/types.h>
  61.  
  62. /*--------------------------------------------------------------------*/
  63. /*                    UUPC/extended include files                     */
  64. /*--------------------------------------------------------------------*/
  65.  
  66. #include "lib.h"
  67. #include "arpadate.h"
  68. #include "checktim.h"
  69. #include "dater.h"
  70. #include "dcp.h"
  71. #include "dcpsys.h"
  72. #include "hlib.h"
  73. #include "hostable.h"
  74. #include "modem.h"
  75. #include "script.h"
  76. #include "security.h"
  77. #include "ssleep.h"
  78. #include "catcher.h"
  79. #include "ulib.h"
  80.  
  81. /*--------------------------------------------------------------------*/
  82. /*                          Global variables                          */
  83. /*--------------------------------------------------------------------*/
  84.  
  85. char *device = NULL;          /*Public to show in login banner     */
  86.  
  87. static char **answer, **initialize, **dropline, **ring, **connect;
  88. static char **noconnect;
  89. static char *dialPrefix, *dialSuffix;
  90.  
  91. static INTEGER chardelay, dialTimeout, modemTimeout, scriptTimeout;
  92. static INTEGER answerTimeout, inspeed;
  93. static INTEGER gWindowSize, gPacketSize;
  94. static INTEGER vWindowSize, vPacketSize;
  95. static INTEGER GWindowSize, GPacketSize;
  96.  
  97. INTEGER M_fPacketSize;
  98. INTEGER M_gPacketTimeout;        /* "g" procotol                  */
  99. INTEGER M_fPacketTimeout;        /* "f" procotol                  */
  100. INTEGER M_MaxErr= 10;         /* Allowed errors per single packet    */
  101. INTEGER M_MaxErr;             /* Allowed errors per single packet    */
  102. INTEGER M_xfer_bufsize;       /* Buffering used for file transfers */
  103.  
  104. boolean bmodemflag[MODEM_LAST];
  105.  
  106. static FLAGTABLE modemFlags[] = {
  107.    { "carrierdetect",  MODEM_CD,          B_LOCAL },
  108.    { "direct",         MODEM_DIRECT,      B_LOCAL },
  109.    { "fixedspeed",     MODEM_FIXEDSPEED,  B_LOCAL },
  110.    { "variablepacket", MODEM_VARIABLEPACKET, B_LOCAL | B_OBSOLETE },
  111.    { "largepacket",    MODEM_LARGEPACKET, B_LOCAL | B_OBSOLETE },
  112.    { nil(char) }
  113. }           ;
  114.  
  115. static CONFIGTABLE modemtable[] = {
  116.    { "answer",        (char **) &answer,       B_LIST   | B_UUCICO },
  117.    { "answertimeout", (char **) &answerTimeout,B_INTEGER| B_UUCICO },
  118.    { "biggpacketsize",(char **) &GPacketSize,  B_INTEGER| B_UUCICO },
  119.    { "biggwindowsize",(char **) &GWindowSize,  B_INTEGER| B_UUCICO },
  120.    { "chardelay",     (char **) &chardelay,    B_INTEGER| B_UUCICO },
  121.    { "connect",       (char **) &connect,      B_LIST   | B_UUCICO },
  122.    { "device",        &device,  B_TOKEN  | B_UUCICO | B_REQUIRED },
  123.    { "dialprefix",    &dialPrefix, B_STRING | B_UUCICO | B_REQUIRED },
  124.    { "dialsuffix",    &dialSuffix,             B_STRING | B_UUCICO },
  125.    { "dialtimeout",   (char **) &dialTimeout,  B_INTEGER| B_UUCICO },
  126.    { "fpacketsize",   (char **) &M_fPacketSize,B_INTEGER| B_UUCICO },
  127.    { "fpackettimeout",(char **) &M_fPacketTimeout, B_INTEGER | B_UUCICO },
  128.    { "gpacketsize",   (char **) &gPacketSize,  B_INTEGER| B_UUCICO },
  129.    { "gpackettimeout",(char **) &M_gPacketTimeout, B_INTEGER | B_UUCICO },
  130.    { "gwindowsize",   (char **) &gWindowSize,  B_INTEGER| B_UUCICO },
  131.    { "hangup",        (char **) &dropline,     B_LIST   | B_UUCICO },
  132.    { "initialize",    (char **) &initialize,   B_LIST   | B_UUCICO },
  133.    { "inspeed",       (char **) &inspeed,      B_INTEGER| B_UUCICO },
  134.    { "maximumerrors", (char **) &M_MaxErr,     B_INTEGER| B_UUCICO },
  135.    { "modemtimeout",  (char **) &modemTimeout, B_INTEGER| B_UUCICO },
  136.    { "noconnect",     (char **) &noconnect,    B_LIST   | B_UUCICO },
  137.    { "options",       (char **) bmodemflag,    B_ALL    | B_BOOLEAN},
  138.    { "porttimeout",   NULL,                    B_OBSOLETE },
  139.    { "ring",          (char **) &ring,         B_LIST   | B_UUCICO },
  140.    { "scripttimeout", (char **) &scriptTimeout,B_INTEGER| B_UUCICO },
  141.    { "transferbuffer",(char **) &M_xfer_bufsize, B_INTEGER| B_UUCICO },
  142.    { "vpacketsize",   (char **) &vPacketSize,  B_INTEGER| B_UUCICO },
  143.    { "vwindowsize",   (char **) &vWindowSize,  B_INTEGER| B_UUCICO },
  144.    { nil(char) }
  145. }; /* modemtable */
  146.  
  147. /*--------------------------------------------------------------------*/
  148. /*                    Internal function prototypes                    */
  149. /*--------------------------------------------------------------------*/
  150.  
  151. static boolean getmodem( const char *brand);
  152.  
  153. static boolean dial(char *number, const size_t speed);
  154.  
  155. static boolean sendlist( char **list, int timeout, int lasttimeout,
  156.                          char **failure);
  157.  
  158. static boolean sendalt( char *string, int timeout, char **failure);
  159.  
  160. static void autobaud( const size_t speed);
  161.  
  162. /*--------------------------------------------------------------------*/
  163. /*              Define current file name for references               */
  164. /*--------------------------------------------------------------------*/
  165.  
  166. currentfile();
  167.  
  168. /*--------------------------------------------------------------------*/
  169. /*    c a l l u p                                                     */
  170. /*                                                                    */
  171. /*    script processor - nothing fancy!                               */
  172. /*--------------------------------------------------------------------*/
  173.  
  174. CONN_STATE callup( void )
  175. {
  176.    char *exp;
  177.    int i;
  178.    size_t speed;
  179.  
  180. /*--------------------------------------------------------------------*/
  181. /*             Announce we are trying to call the system              */
  182. /*--------------------------------------------------------------------*/
  183.  
  184.    printmsg(1, "callup: calling \"%s\" via %s at %s on %s",
  185.           rmtname, flds[FLD_TYPE], flds[FLD_SPEED], arpadate());
  186.  
  187.    speed = (size_t) atoi( flds[FLD_SPEED] );
  188.    if (speed < 300)
  189.    {
  190.       printmsg(0,"callup: Modem speed \"%s\" is invalid.",
  191.                   flds[FLD_SPEED]);
  192.       hostp->hstatus = invalid_device;
  193.       return CONN_INITIALIZE;
  194.    }
  195.  
  196. /*--------------------------------------------------------------------*/
  197. /*                     Get the modem information                      */
  198. /*--------------------------------------------------------------------*/
  199.  
  200.    if (!getmodem(flds[FLD_TYPE]))
  201.    {
  202.       hostp->hstatus = invalid_device;
  203.       return CONN_INITIALIZE;
  204.    }
  205.  
  206. /*--------------------------------------------------------------------*/
  207. /*                         Dial the telephone                         */
  208. /*--------------------------------------------------------------------*/
  209.  
  210.    if (! dial(flds[FLD_PHONE],speed))
  211.       return CONN_DROPLINE;
  212.  
  213. /*--------------------------------------------------------------------*/
  214. /*             The modem is connected; now login the host             */
  215. /*--------------------------------------------------------------------*/
  216.  
  217.    for (i = FLD_EXPECT; i < kflds; i += 2) {
  218.  
  219.       exp = flds[i];
  220.       printmsg(2, "expecting %d of %d \"%s\"", i, kflds, exp);
  221.       if (!sendalt( exp, scriptTimeout , noconnect))
  222.       {
  223.          printmsg(0, "SCRIPT FAILED");
  224.          hostp->hstatus =  script_failed;
  225.          return CONN_DROPLINE;
  226.       } /* if */
  227.  
  228.       printmsg(2, "callup: sending %d of %d \"%s\"",
  229.                    i + 1, kflds, flds[i + 1]);
  230.       sendstr(flds[i + 1]);
  231.  
  232.    } /*for*/
  233.  
  234.    return CONN_PROTOCOL;
  235.  
  236. } /*callup*/
  237.  
  238. /*--------------------------------------------------------------------*/
  239. /*    c a l l h o t                                                   */
  240. /*                                                                    */
  241. /*    Initialize processing when phone is already off the hook        */
  242. /*--------------------------------------------------------------------*/
  243.  
  244. CONN_STATE callhot( const BPS xspeed )
  245. {
  246.    BPS speed;
  247.  
  248. /*--------------------------------------------------------------------*/
  249. /*                        Open the serial port                        */
  250. /*--------------------------------------------------------------------*/
  251.  
  252.    if (E_inmodem == NULL)
  253.    {
  254.       printmsg(0,"callin: No modem name supplied for incoming calls!");
  255.       panic();
  256.    } /* if */
  257.  
  258.    if (!getmodem(E_inmodem))  /* Initialize modem configuration      */
  259.       panic();                /* Avoid loop if bad modem name        */
  260.  
  261. /*--------------------------------------------------------------------*/
  262. /*                        Set the modem speed                         */
  263. /*--------------------------------------------------------------------*/
  264.  
  265.    if ( xspeed == 0)
  266.       speed = inspeed;
  267.    else
  268.       speed = xspeed;
  269.  
  270. /*--------------------------------------------------------------------*/
  271. /*                    Open the communications port                    */
  272. /*--------------------------------------------------------------------*/
  273.  
  274.    if (openline(device, speed, bmodemflag[MODEM_DIRECT] ))
  275.       panic();
  276.  
  277. /*--------------------------------------------------------------------*/
  278. /*                          Initialize stats                          */
  279. /*--------------------------------------------------------------------*/
  280.  
  281.    memset( &remote_stats, 0, sizeof remote_stats);
  282.                               /* Clear remote stats for login        */
  283.    time(&remote_stats.ltime); /* Remember time of last attempt conn  */
  284.    remote_stats.calls ++ ;
  285.    return CONN_HOTLOGIN;
  286.  
  287. } /* callhot */
  288.  
  289. /*--------------------------------------------------------------------*/
  290. /*    c a l l i n                                                     */
  291. /*                                                                    */
  292. /*    Answer the modem in passive mode                                */
  293. /*--------------------------------------------------------------------*/
  294.  
  295. CONN_STATE callin( const time_t exit_time )
  296. {
  297.    char c;                    /* A character for input buffer        */
  298.  
  299.    int    offset;             /* Time to wait for telephone          */
  300.    time_t left;
  301.  
  302. /*--------------------------------------------------------------------*/
  303. /*    Determine how long we can wait for the telephone, up to         */
  304. /*    MAX_INT seconds.  Aside from Turbo C limits, this insures we    */
  305. /*    kick the modem once in a while.                                 */
  306. /*--------------------------------------------------------------------*/
  307.  
  308.       left =  exit_time - time(NULL);
  309.       if ( left < 0 )               /* Any time left?                */
  310.          return CONN_EXIT;             /* No --> shutdown            */
  311.  
  312.       if ( left > INT_MAX)
  313.          offset = INT_MAX;
  314.       else
  315.          offset = (int) left;
  316.  
  317. /*--------------------------------------------------------------------*/
  318. /*                        Open the serial port                        */
  319. /*--------------------------------------------------------------------*/
  320.  
  321.    if (E_inmodem == NULL)
  322.    {
  323.       printmsg(0,"callin: No modem name supplied for incoming calls!");
  324.       panic();
  325.    } /* if */
  326.  
  327.    if (!getmodem(E_inmodem))  /* Initialize modem configuration      */
  328.       panic();                /* Avoid loop if bad modem name        */
  329.  
  330.    if ((ring == NULL) || (inspeed == 0))
  331.    {
  332.       printmsg(0,"callin: Missing inspeed and/or ring values in modem \
  333. configuration file.");
  334.       panic();
  335.    } /* if */
  336.  
  337. /*--------------------------------------------------------------------*/
  338. /*                    Open the communications port                    */
  339. /*--------------------------------------------------------------------*/
  340.  
  341.    if (openline(device, inspeed, bmodemflag[MODEM_DIRECT]))
  342.       panic();
  343.  
  344. /*--------------------------------------------------------------------*/
  345. /*              Flush the input buffer of any characters              */
  346. /*--------------------------------------------------------------------*/
  347.  
  348.    while (sread(&c ,1,0));    /* Discard trailing trash from modem
  349.                                  connect message                     */
  350.  
  351. /*--------------------------------------------------------------------*/
  352. /*                        Initialize the modem                        */
  353. /*--------------------------------------------------------------------*/
  354.  
  355.    if (!sendlist( initialize, modemTimeout, modemTimeout, NULL))
  356.    {
  357.       printmsg(0,"callin: Modem failed to initialize");
  358.       panic();
  359.    }
  360.  
  361. /*--------------------------------------------------------------------*/
  362. /*                   Wait for the telephone to ring                   */
  363. /*--------------------------------------------------------------------*/
  364.  
  365.    printmsg(1,"callin: Monitoring port %s device %s"
  366.                      " for %d minutes until %s",
  367.                      device, E_inmodem , (int) (offset / 60),
  368.                       dater( exit_time , NULL));
  369.  
  370.    interactive_processing = FALSE;
  371.  
  372.    if (!sendlist( ring,modemTimeout, offset, noconnect))
  373.                               /* Did it ring?                        */
  374.    {
  375.       interactive_processing = TRUE;
  376.       shutdown();
  377.       return CONN_INITIALIZE;     /* No --> Return to caller       */
  378.    }
  379.  
  380.    interactive_processing = TRUE;
  381.  
  382.    if(!sendlist(answer, modemTimeout,answerTimeout, noconnect))
  383.                               /* Pick up the telephone               */
  384.    {
  385.       printmsg(1,"callin: Modem failed to connect to incoming call");
  386.       shutdown();
  387.       return CONN_INITIALIZE;
  388.    }
  389.  
  390. /*--------------------------------------------------------------------*/
  391. /*           The modem is connected; now try to autobaud it           */
  392. /*--------------------------------------------------------------------*/
  393.  
  394.    printmsg(14, "callin: got CONNECT");
  395.  
  396.    if (bmodemflag[MODEM_CD])
  397.       CD();                   /* Set the carrier detect flags        */
  398.  
  399.    autobaud(inspeed);         /* autobaud the modem                  */
  400.  
  401. /*--------------------------------------------------------------------*/
  402. /*        Flush the input buffer of any other input characters        */
  403. /*--------------------------------------------------------------------*/
  404.  
  405.    while (sread(&c ,1,0));    /* Discard trailing trash from modem
  406.                                  connect message                     */
  407.  
  408.    memset( &remote_stats, 0, sizeof remote_stats);
  409.                               /* Clear remote stats for login        */
  410.    time(&remote_stats.ltime); /* Remember time of last attempt conn  */
  411.    remote_stats.calls ++ ;
  412.    return CONN_LOGIN;
  413.  
  414. } /* callin */
  415.  
  416. /*--------------------------------------------------------------------*/
  417. /*    g e t m o d e m                                                 */
  418. /*                                                                    */
  419. /*    Read a modem configuration file                                 */
  420. /*--------------------------------------------------------------------*/
  421.  
  422. static boolean getmodem( const char *brand)
  423. {
  424.    char filename[FILENAME_MAX];
  425.    static char *modem = NULL;
  426.    FILE *fp;
  427.    CONFIGTABLE *tptr;
  428.    size_t subscript;
  429.    boolean success;
  430.  
  431. /*--------------------------------------------------------------------*/
  432. /*                      Validate the modem name                       */
  433. /*--------------------------------------------------------------------*/
  434.  
  435.    if (equal(modem, brand))   /* Already initialized?                */
  436.       return TRUE;            /* Yes --> Don't process it again      */
  437.  
  438. /*--------------------------------------------------------------------*/
  439. /*                        Initialize the table                        */
  440. /*--------------------------------------------------------------------*/
  441.  
  442.    for (tptr = modemtable; tptr->sym != nil(char); tptr++)
  443.       if (tptr->bits & (B_TOKEN | B_STRING | B_LIST | B_CLIST))
  444.          *(tptr->loc) = nil(char);
  445.  
  446.    for (subscript = 0; subscript < MODEM_LAST; subscript++)
  447.       bmodemflag[subscript] = FALSE;
  448.  
  449.    chardelay = 00;            /* Default is no delay between chars    */
  450.    dialTimeout = 40;          /* Default is 40 seconds to dial phone  */
  451.    gPacketSize = SMALL_PACKET;
  452.    vPacketSize = MAXPACK;
  453.    GPacketSize = MAXPACK;
  454.    gWindowSize = 0;
  455.    vWindowSize = 0;
  456.    GWindowSize = 0;
  457.    M_fPacketSize = MAXPACK;
  458.    M_fPacketTimeout = 20;
  459.    M_gPacketTimeout = 10;
  460.    modemTimeout  = 3;         /* Default is 3 seconds for modem cmds  */
  461.    scriptTimeout = 30;        /* Default is 30 seconds for script data*/
  462.    M_xfer_bufsize = BUFSIZ;   /* Buffering used for file transfers    */
  463.    M_MaxErr= 10;              /* Allowed errors per single packet     */
  464.  
  465. /*--------------------------------------------------------------------*/
  466. /*                 Open the modem configuration file                  */
  467. /*--------------------------------------------------------------------*/
  468.  
  469.    if (equaln(brand,"COM",3))
  470.    {
  471.       printmsg(0,"Modem type \"%s\" is invalid; Snuffles suspects \
  472. your %s file is obsolete.", brand, SYSTEMS);
  473.       panic();
  474.    }
  475.  
  476.    sprintf(filename,"%s/%s.MDM",E_confdir, brand);
  477.    if ((fp = FOPEN(filename, "r", TEXT)) == nil(FILE))
  478.    {
  479.       printmsg(0,"getmodem: Unable to locate configuration for %s",
  480.                brand);
  481.       printerr( filename );
  482.       return FALSE;
  483.    }
  484.  
  485. /*--------------------------------------------------------------------*/
  486. /*                We got the file open, now process it                */
  487. /*--------------------------------------------------------------------*/
  488.  
  489.    printmsg(3,"getmodem: loading modem configuration file %s", filename);
  490.    success = getconfig(fp, MODEM_CONFIG, B_UUCICO, modemtable, modemFlags);
  491.    fclose(fp);
  492.    if (!success)
  493.       return FALSE;
  494.  
  495. /*--------------------------------------------------------------------*/
  496. /*         Verify all required modem parameters were supplied         */
  497. /*--------------------------------------------------------------------*/
  498.  
  499.    success = TRUE;
  500.    for (tptr = modemtable; tptr->sym != nil(char); tptr++) {
  501.       if ((tptr->bits & (B_REQUIRED | B_FOUND)) == B_REQUIRED)
  502.       {
  503.          printmsg(0, "getmodem: configuration parameter \"%s\" must be set.",
  504.             tptr->sym);
  505.          success = FALSE;
  506.       } /* if */
  507.    } /* for */
  508.  
  509.    if ( success )             /* Good modem setup?                   */
  510.       modem = newstr(brand);  /* Yes --> Remember it for next time   */
  511.  
  512.    return success;
  513.  
  514. } /* getmodem */
  515.  
  516. /*--------------------------------------------------------------------*/
  517. /*    d i a l                                                         */
  518. /*                                                                    */
  519. /*    Generic modem dialer; only major limitation is that autoabaud   */
  520. /*    strings are not configurable                                    */
  521. /*--------------------------------------------------------------------*/
  522.  
  523. static boolean dial(char *number, const size_t speed)
  524. {
  525.    char buf[81];
  526.  
  527. /*--------------------------------------------------------------------*/
  528. /*                        Open the serial port                        */
  529. /*--------------------------------------------------------------------*/
  530.  
  531.    if (openline(device, speed, bmodemflag[MODEM_DIRECT]))
  532.    {
  533.  
  534.       hostp->hstatus =  nodevice;
  535.       return FALSE;
  536.    }
  537.  
  538. /*--------------------------------------------------------------------*/
  539. /*              Flush the input buffer of any characters              */
  540. /*--------------------------------------------------------------------*/
  541.  
  542.    while (sread(buf,1,0));    /* Discard trailing trash from modem
  543.                                  connect message                     */
  544.  
  545. /*--------------------------------------------------------------------*/
  546. /*                        Initialize the modem                        */
  547. /*--------------------------------------------------------------------*/
  548.  
  549.    if (!sendlist( initialize, modemTimeout, modemTimeout, noconnect))
  550.    {
  551.       printmsg(0,"dial: Modem failed to initialize");
  552.       hostp->hstatus =  dial_script_failed;
  553.       return FALSE;
  554.    }
  555.  
  556. /*--------------------------------------------------------------------*/
  557. /*           Setup the dial string and then dial the modem            */
  558. /*--------------------------------------------------------------------*/
  559.  
  560.    strcpy(buf, dialPrefix);
  561.    strcat(buf, number);
  562.    if (dialSuffix != NULL)
  563.       strcat(buf, dialSuffix);
  564.  
  565.    sendstr( buf );         /* Send the command to the telephone      */
  566.  
  567.    if (!sendlist(connect,  modemTimeout, dialTimeout, noconnect))
  568.    {
  569.       hostp->hstatus =  dial_failed;
  570.       return FALSE;
  571.    }
  572.    printmsg(3, "dial: Modem reports connected");
  573.  
  574.    if (bmodemflag[MODEM_CD])
  575.       CD();                   /* Set the carrier detect flags        */
  576.  
  577.    time( &remote_stats.lconnect );
  578.    remote_stats.calls ++ ;
  579.  
  580.    autobaud(speed);        /* Reset modem speed, if desired          */
  581.  
  582. /*--------------------------------------------------------------------*/
  583. /*                      Report success to caller                      */
  584. /*--------------------------------------------------------------------*/
  585.  
  586.    return TRUE;            /* Dial succeeded    */
  587.  
  588. } /* dial */
  589.  
  590. /*--------------------------------------------------------------------*/
  591. /*    a u t o b a u d                                                 */
  592. /*                                                                    */
  593. /*    autobaud a modem which has just connected                       */
  594. /*--------------------------------------------------------------------*/
  595.  
  596. static void autobaud( const size_t speed )
  597. {
  598.    char buf[10];
  599.  
  600.    ssleep(1);                 /*  Allow modem port to stablize       */
  601.  
  602. /*--------------------------------------------------------------------*/
  603. /*                  Autobaud the modem if requested                   */
  604. /*--------------------------------------------------------------------*/
  605.  
  606.    if (!bmodemflag[MODEM_FIXEDSPEED])
  607.    {
  608.       size_t len = 0;
  609.  
  610.       memset( buf, '\0', sizeof( buf ));  /* Zero buffer                */
  611.       while ((len < sizeof buf) && sread( &buf[len],1,0))
  612.          len = strlen( buf );             /* Get speed into buffer      */
  613.  
  614.       if (len > 5)
  615.       {
  616.          char  *token;           /* Pointer to buffer value */
  617.          token = strtok(buf,WHITESPACE);
  618.          if (strlen(token))
  619.          {
  620.             size_t new_speed = (unsigned) atoi(token);
  621.             if ((new_speed != speed) && (new_speed > 300))
  622.             {
  623.                printmsg(2, "autobaud: speed select %s", token);
  624.                SIOSpeed(atoi(token));
  625.             } /* if */
  626.          } /* if */
  627.       } /* if */
  628.       else
  629.          printmsg(3, "autobaud: unable to speed select, using %d", speed);
  630.    } /* if */
  631.  
  632. } /* autobaud */
  633.  
  634. /*--------------------------------------------------------------------*/
  635. /*    s h u t d o w n                                                 */
  636. /*                                                                    */
  637. /*    Terminate modem processing via hangup                           */
  638. /*--------------------------------------------------------------------*/
  639.  
  640. void shutdown( void )
  641. {
  642.    static boolean recurse = FALSE;
  643.  
  644.    if ( ! port_active )          /* Allowed for Ctrl-Break           */
  645.       return;
  646.  
  647.    if ( !recurse )
  648.    {
  649.       boolean aborted = terminate_processing;
  650.       recurse = TRUE;
  651.       terminate_processing = FALSE;
  652.       hangup();
  653.       sendlist( dropline, modemTimeout, modemTimeout, NULL);
  654.       recurse = FALSE;
  655.       terminate_processing |= aborted;
  656.    }
  657.  
  658.    closeline();
  659. }
  660.  
  661. /*--------------------------------------------------------------------*/
  662. /*    s e n d l i s t                                                 */
  663. /*                                                                    */
  664. /*    Send a NULL terminated list of send/expect strings              */
  665. /*--------------------------------------------------------------------*/
  666.  
  667. static boolean sendlist(   char **list,
  668.                            int timeout,
  669.                            int lasttimeout,
  670.                            char **failure)
  671. {
  672.    boolean expect = TRUE;
  673.  
  674.    if (list == NULL)          /* Was the field supplied?             */
  675.       return TRUE;            /* No --> Must be optional, return     */
  676.  
  677. /*--------------------------------------------------------------------*/
  678. /*     Run through the list, alternating expect and send strings      */
  679. /*--------------------------------------------------------------------*/
  680.  
  681.    while( *list != NULL)
  682.    {
  683.  
  684.       if (expect)
  685.       {
  686.          char *exp = strdup( *list );
  687.          boolean success;
  688.          checkref( exp );
  689.          success = sendalt( exp,
  690.                             (*(++list) == NULL) ? lasttimeout : timeout,
  691.                             failure);
  692.          free( exp );
  693.          if (!success)
  694.             return FALSE;
  695.       }
  696.       else
  697.          sendstr( *list++ );
  698.       expect = ! expect;
  699.    } /* while */
  700.  
  701. /*--------------------------------------------------------------------*/
  702. /*    If we made it this far, success is at hand; return to caller    */
  703. /*--------------------------------------------------------------------*/
  704.  
  705.    return TRUE;
  706. } /* sendlist */
  707.  
  708. /*--------------------------------------------------------------------*/
  709. /*    s e n d a l t                                                   */
  710. /*                                                                    */
  711. /*    Expect a string, with alternates                                */
  712. /*--------------------------------------------------------------------*/
  713.  
  714. static boolean sendalt( char *exp, int timeout, char **failure)
  715. {
  716.    int ok;
  717.  
  718.    for ( ;; )
  719.    {
  720.       char *alternate = strchr(exp, '-');
  721.  
  722.       if (alternate != nil(char))
  723.          *alternate++ = '\0';
  724.  
  725.       ok = expectstr(exp, timeout, failure);
  726.  
  727.       if ( terminate_processing )
  728.       {
  729.          shutdown();
  730.          return FALSE;
  731.       }
  732.  
  733.       if (ok || (alternate == nil(char)))
  734.          return (ok == 1);
  735.  
  736.  
  737.       if (bmodemflag[MODEM_CD] && ! CD())
  738.       {
  739.          printmsg(0,"sendalt: Serial port reports modem not ready");
  740.          return FALSE;
  741.       }
  742.  
  743.       exp = strchr(alternate, '-');
  744.       if (exp != nil(char))
  745.          *exp++ = '\0';
  746.  
  747.       printmsg(0, "sending alternate");
  748.       sendstr(alternate);
  749.    } /*for*/
  750.  
  751. } /* sendalt */
  752.  
  753. /*--------------------------------------------------------------------*/
  754. /*    s l o w w r i t e                                               */
  755. /*                                                                    */
  756. /*    Write characters to the serial port at a configurable           */
  757. /*    snail's pace.                                                   */
  758. /*--------------------------------------------------------------------*/
  759.  
  760. void slowwrite( char *s, int len)
  761. {
  762.    swrite( s , len );
  763.    if (chardelay > 0)
  764.       ddelay(chardelay);
  765. } /* slowwrite */
  766.  
  767. /*--------------------------------------------------------------------*/
  768. /*    G e t G W i n d o w                                             */
  769. /*                                                                    */
  770. /*    Report the size of the allowed window for the "g" protocol      */
  771. /*--------------------------------------------------------------------*/
  772.  
  773. INTEGER  GetGWindow(  INTEGER maxvalue , const char protocol )
  774. {
  775.    INTEGER ourWindowSize = 0;
  776.  
  777.    switch( protocol )
  778.    {
  779.       case 'g':
  780.          ourWindowSize = gWindowSize;
  781.          break;
  782.  
  783.       case 'G':
  784.          ourWindowSize = GWindowSize;
  785.          break;
  786.  
  787.       case 'v':
  788.          ourWindowSize = vWindowSize;
  789.          break;
  790.  
  791.       default:
  792.          printmsg(0,"GetGWindow: Invalid protocol %c",protocol);
  793.          panic();
  794.    }
  795.  
  796.    if ( (ourWindowSize < 1 ) || (ourWindowSize > maxvalue))
  797.       return maxvalue;
  798.    else
  799.       return ourWindowSize;
  800.  
  801. } /* GetGWindow */
  802.  
  803. /*--------------------------------------------------------------------*/
  804. /*    G e t G P a c k e t                                             */
  805. /*                                                                    */
  806. /*    Return the allowed packet size for the "g" procotol             */
  807. /*--------------------------------------------------------------------*/
  808.  
  809. INTEGER  GetGPacket( INTEGER maxvalue , const char protocol)
  810. {
  811.    INTEGER savePacketSize ;
  812.    INTEGER ourPacketSize = 0;
  813.    int bits = 6;              /* Minimum Packet Size is 64 bytes     */
  814.  
  815.    switch( protocol )
  816.    {
  817.       case 'g':
  818.          ourPacketSize = gPacketSize;
  819.          break;
  820.  
  821.       case 'G':
  822.          ourPacketSize = GPacketSize;
  823.          break;
  824.  
  825.       case 'v':
  826.          ourPacketSize = vPacketSize;
  827.          break;
  828.  
  829.       default:
  830.          printmsg(0,"GetGPacket: Invalid protocol %c",protocol);
  831.          panic();
  832.    }
  833.  
  834.    savePacketSize = ourPacketSize;
  835.  
  836. /*--------------------------------------------------------------------*/
  837. /*                 Insure the value is a power of two                 */
  838. /*--------------------------------------------------------------------*/
  839.  
  840.    while( (ourPacketSize >> (bits+1)) > 0 )
  841.       bits++;
  842.  
  843.    ourPacketSize = (ourPacketSize >> bits) << bits;
  844.    if ( savePacketSize != ourPacketSize )
  845.       printmsg(0,"packetsize for %c protocol rounded down from %d to %d",
  846.                protocol,
  847.                (int) savePacketSize, (int) ourPacketSize );
  848.  
  849. /*--------------------------------------------------------------------*/
  850. /*    Return the smaller of the argument (the largest packet size     */
  851. /*    the packet driver supports) or what the modem file allows.      */
  852. /*--------------------------------------------------------------------*/
  853.  
  854.    if ( (ourPacketSize < 1 ) || (ourPacketSize > maxvalue))
  855.       return maxvalue;
  856.    else
  857.       return ourPacketSize;
  858.  
  859. } /* GetGPacket */
  860.